#include<iostream>
#include<future>
#include<functional>
#include<thread>
#include<memory>
using func=std::function<int(int,int)>;
int Add(int x,int y)
{
    std::cout<<"in add"<<std::endl;
    return x+y;
}
/*
Task 类的构造函数接受一个 func&（非 const 引用），但传递 Add 函数时会导致编译错误。
这是因为函数指针（如 Add）不能直接绑定到 std::function 的非 const 引用。以下是修复方案和解释：
函数指针与 std::function 的隐式转换‌
Add 是一个函数指针（int(*)(int, int)），
而 std::function 的构造函数允许从函数指针隐式构造临时对象。临时对象不能绑定到非 const 引用。
临时对象‌：函数指针隐式转换生成的 std::function 临时对象需通过 const& 传递。
*/
struct Task
{
    //std::function 的构造函数允许从函数指针隐式构造临时对象
    //而这个临时对象在Task的构造函数结束前都会存在
    Task(const func& f):add(f)
    {}
    //重载的()可以接收任意参数，因为（）不属于单目或者双目操作符
    int operator ()(int a,int b)
    {
        return add(a,b);
    }

    std::function<int(int,int)> add;

};

int main()
{
    //1 模板类封装函数成一个可调用对象,定义一个模板类对象把函数地址传进去
    //模板类显示指定的类型要为函数的类型
    std::shared_ptr<std::packaged_task<int(int,int)>> task=std::make_shared<std::packaged_task<int(int,int)>>(Add);
    //获取可调用对象中关联的future对象
    std::future<int> f =task->get_future();

    //std::packaged_task<int(int,int)> task 对象是不允许拷贝和赋值的
    //所以使用智能指针和lamda表达式的值捕捉拷贝智能指针对象
    //因为智能指针对象的拷贝是把内部维护的std::packaged_task<int(int,int)>
    //指针即地址拷贝过来了没有拷贝对象
    //类使用仿函数,把该调用对象传递到一个线程内部去执行
    std::thread p(
        [task](){
            (*task)(11,22);
        }
    );
    //future对象获取结果
    std::cout<<f.get()<<std::endl;


    Task t(Add);
    std::cout<<t(11,23)<<std::endl;
    p.join();
}